package user

import (
	"context"
	"github.com/pkg/errors"
	"go-zero-demo/common/cache"
	"go-zero-demo/common/utils"
	"go-zero-demo/common/xerr"

	"go-zero-demo/apps/user/cmd/api/internal/svc"
	"go-zero-demo/apps/user/cmd/api/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

var ErrPhoneVerify = xerr.NewErrMsg("phone not verify")
var ErrVerifyCodeExist = xerr.NewErrMsg("verify code is exist")
var ErrSetVerifyCode = xerr.NewErrMsg("set verify code err")
var PhoneCacheKey = "phone_verify_code_"

type GetVerifyCodeLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

// 获取验证码
func NewGetVerifyCodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetVerifyCodeLogic {
	return &GetVerifyCodeLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *GetVerifyCodeLogic) GetVerifyCode(req *types.VerifyCodeReq) (resp *types.VerifyCodeResp, err error) {
	// 参数校验
	if validateResult := l.svcCtx.Validator.Validate(req); len(validateResult) > 0 {
		return nil, xerr.NewErrMsg(validateResult)
	}
	phoneVerify := utils.CheckPhone(req.Phone)
	if !phoneVerify {
		return nil, errors.Wrapf(ErrPhoneVerify, "phone not verify: %s", req.Phone)
	}

	redisClient := cache.NewRedisClient(l.svcCtx.RedisClient)
	cacheKey := PhoneCacheKey + req.Phone
	verifyCode, err := redisClient.Exists(l.ctx, cacheKey)
	if verifyCode || err != nil {
		return nil, errors.Wrapf(ErrVerifyCodeExist, "verify code is exist: %s", req.Phone)
	}

	newVerifyCode := utils.GenerateRandomString(6)
	err = redisClient.Set(l.ctx, cacheKey, newVerifyCode)
	if err != nil {
		return nil, errors.Wrapf(ErrSetVerifyCode, "set verify code err: %s", req.Phone)
	}
	err = redisClient.Expire(l.ctx, cacheKey, 120)
	if err != nil {
		_, _ = redisClient.Delete(l.ctx, cacheKey)
		return nil, errors.Wrapf(ErrSetVerifyCode, "set verify code err: %s", req.Phone)
	}

	return &types.VerifyCodeResp{
		VerifyCode: newVerifyCode,
	}, nil
}
